/* 
 * File:   UartHelper.cpp
 * Author: root
 * 
 * Created on May 8, 2020, 4:38 PM
 */

#include "UartHelper.h"

int speed_arr[] = { B4000000, B1152000, B921600, B500000, B460800, B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300,
                    B4000000, B1152000, B921600, B500000, B460800, B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300,
                  };
int name_arr[] = { 4000000, 1152000, 921600, 500000, 460800, 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300,
                   4000000, 1152000, 921600, 500000, 460800, 115200, 38400, 19200, 9600, 4800, 2400, 1200, 300,
                 };

UartHelper::UartHelper() 
{
    
}

UartHelper::UartHelper(const UartHelper& orig) 
{
    
}

UartHelper::~UartHelper() 
{
    if(fd >= 0) {
        close(fd);
    }
}

void UartHelper::set_speed(int fd, int speed)
{
    int   i;
    int   status;
    struct termios   Opt;
    tcgetattr(fd, &Opt);
    Opt.c_cflag |= (CLOCAL |CREAD);
    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
    {
        if(speed == name_arr[i])
        {
            tcflush(fd, TCIOFLUSH);
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            status = tcsetattr(fd, TCSANOW, &Opt);
            if  (status != 0)
            {
                perror("set_speed tcsetattr fd");
            }
            return;
        }
        tcflush(fd,TCIOFLUSH);
    }
}

int UartHelper::set_Parity(int fd, int databits, int stopbits, int parity)
{
    struct termios options;
    if  ( tcgetattr( fd,&options)  !=  0)
    {
        perror("SetupSerial 1");
        return -1;
    }
//    cfmakeraw(&options);
//    options.c_cflag &= ~(CSIZE | CRTSCTS);
    options.c_cflag &= ~CSIZE;
    switch (databits) /*鐠佸墽鐤嗛弫鐗堝祦娴ｅ秵鏆�*/
    {
    case 7:
        options.c_cflag |= CS7;//
        break;
    case 8:
        options.c_cflag |= CS8;
        break;
    default:
        fprintf(stderr,"Unsupported data size\n");
        return -1;
    }
    switch (parity)
    {
    case 'n':
    case 'N':
        options.c_cflag &= ~PARENB;   /* Clear parity enable */
        options.c_iflag &= ~INPCK;     /* Enable parity checking */
        break;
    case 'o':
    case 'O':
        options.c_cflag |= (PARODD | PARENB);  /* 鐠佸墽鐤嗘稉鍝勵殞閺佸牓鐛�*/
        options.c_iflag |= INPCK;             /* Disnable parity checking */
        break;
    case 'e':
    case 'E':
        options.c_cflag |= PARENB;     /* Enable parity */
        options.c_cflag &= ~PARODD;   /* 鏉烆剚宕叉稉鍝勪紦閺佸牓鐛�*/
        options.c_iflag |= INPCK;       /* Disnable parity checking */
        break;
    case 'S':
    case 's':  /*as no parity*/
        options.c_cflag &= ~PARENB;
        options.c_cflag &= ~CSTOPB;
        break;
    default:
        fprintf(stderr,"Unsupported parity\n");
        return -1;
    }
    /* 鐠佸墽鐤嗛崑婊勵剾娴ｏ拷*/
    switch (stopbits)
    {
    case 1:
        options.c_cflag &= ~CSTOPB;
        break;
    case 2:
        options.c_cflag |= CSTOPB;
        break;
    default:
        fprintf(stderr,"Unsupported stop bits\n");
        return -1;
    }
    /* Set input parity option */
    if (parity != 'n')
    {
        options.c_iflag |= INPCK;
    }
    options.c_cc[VTIME] = 0; // options.c_cc[VTIME] = 10; // 1 seconds 鐡掑懏妞傞弮鍫曟？  閺�瑙勫灇闂冭顢ｉ幒銉︽暪
    options.c_cc[VMIN] = 1; // options.c_cc[VMIN] = 0;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_iflag &= ~(INLCR | ICRNL | IGNCR | IXON | BRKINT |IXOFF);
    options.c_oflag &= ~(ONLCR | OCRNL | ONOCR | ONLRET | OPOST);
    tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
    if (tcsetattr(fd,TCSANOW,&options) != 0)
    {
        perror("SetupSerial 3");
        return -1;
    }
    return 1;
}

int UartHelper::uartOpen(char *deviceName)
{
    fd = open(deviceName, O_RDWR|O_NDELAY);

    return fd;
}

char UartHelper::initSerialDev(int fd, int speed, int databits, int stopbits, int parity)
{
    if (fd <= 0) return -1;
    set_speed(fd,speed);

    if (set_Parity(fd,databits,stopbits,parity)== -1)
    {
        printf("Set fd %d Parity Error\n",fd);
        return -1;
    }

    return 0;
}

int UartHelper::uartRead(char *buf, int len)
{
    return read(fd, buf, len);
}
